<?php
/**
 * Objeto Model
 * @package mc
 */
/**
 * @package mc
 */
class Model {

	/**
	 * Objeto banco de dados
	 */
	public $db	= null;
	
	/**
	 * Objeto DAO, contém nome da tabela suas propriedades e também seus campos
	 */
	public $dao	= array();
	
	/**
	 * nome da chave, só para facilitar nos logs.
	 */
	public $chave = "";
	
	/**
	 * matriz com todos os erros gerados ao executar sql
	 */
	public $erros = array();
	
	/**
	 * função end
	 * @return void
	 */
	function __destruct()
	{
		$this->closeDb();
	}
	
	/**
	 * Fecha a conexão com o banco de dados
	 */
	public function closeDb()
	{
		// desconectando no banco de dados
		if (method_exists($this->db,"IsConnected"))
		{
			if ($this->db->IsConnected())
			{
				$this->db->Close(); 
			}
		}
	}
	
	/**
	 * Retorna o resultado de uma query
	 * @param string $sql Linha SQL a ser executada
	 * @limite array $limite Matriz contendo limite da query, o formato x,y
	 * @return string $retorno;
	 */
	public function Execute($sql="",$limite=array())
	{
		// instanciando o banco de dados, caso o mesmo já não tenha sido instanciado.
		$this->setDb();
		
		// executando a sql
		if (!count($limite))
		{
			$retorno = $this->db->Execute($sql);
		} else
		{
			$retorno = $this->db->SelectLimit($sql,$limite[0],$limite[1]);
		}
		
		// se ocorreu algum erro, retorna o erro e guarda o seu valor na matriz erros
		if ($this->db->ErrorMsg())
		{
			$retorno = $this->db->ErrorMsg();
			array_unshift($this->erros,$this->chave." : ".$retorno);
		}

		// retorno		
		return $retorno;
	}
	
	/**
	 * Retorna o objeto de banco de dados já conectado
	 * @return $retorno boolean True para conexão ok e False para falha na conexão
	 */
	public function setDb()
	{
		// conectando no banco de dados
		if (!method_exists($this->db,"IsConnected"))
		{
			// incluindo adodb
			$arquivo = _dir_libs."adodb5/adodb.inc.php";
			if (file_exists($arquivo)) require_once($arquivo); else exit("Não foi possível localizar $arquivo");
			
			// incluindo configurações
			$arquivo = "config.php";
			if (file_exists($arquivo)) require($arquivo); else exit("Para que o Model funcione é necessário o arquivo de configuração");
			$this->db 							= NewADOConnection($driver);
			if (!$this->db->database) $this->db->database					= $banco;
			$this->db->user						= $usuario;
			$this->db->password					= $senha;
			$this->db->host						= $host;
			if (!$this->db->IsConnected())
			{
				$this->db->Connect();
				if ($driver=="mysql")
				{
					@$this->db->Execute("SET NAMES 'utf8'");
				}
			}
			if ($this->db->ErrorMsg())
			{
				$msg = "<p>Verifique junto ao seu DBA se o banco foi criado e configurado corretamente conforme configura&ccedil;&atilde;o do arquivo <strong>config.php</strong><br />\n<br />\n";
				if ($driver=="mysql")
				{
					$msg .= "Talvez seja necess&aacute;rio que o seu DBA execute as seguintes linhas:<br />\n<br />\n";
					if ($driver=="mysql") $msg .= "set names 'utf8';<br />\n";
					$msg .= "create database $banco;<br />\n";
					$msg .= "grant all privileges on $banco.* to $usuario@localhost identified by '$senha' with grant option;<br />\n";
					$msg .= "flush privileges;<br /><br />\n";
					$msg .= "<center>clique <a href='.'>aqui</a> para tentar novamente.</center>";
				}
				$msg .= "</p>";
				exit("<strong>".$this->db->ErrorMsg()."</strong><br />\n".$msg);
			}
		}
	}
	
	/**
	 * retorn ao tipo do banco, conforme resultado da adoDB
	 * @param string $t valor retornar pela adoDB
	 * @return string 
	 */
	private function getTipo($t="")
	{
		switch($t)
		{
			case "D":
				return "date";
				break;
			case "I":
				return "numero";
				break;
			case "T":
				return "timestamp";
				break;
			default:
				return "text";
		}
	}
	
	/**
	 * Configura o objeto DADO do model
	 * @param string $tab Nome da tabela
	 * @param array  $cam Matrizm contendo o nome de cada campo a ser configurado, se ignorado, configura todos os campos.
	 * @param string $filtro Se possui valor, incrementa a sql com WHERE
	 * @return void
	 */
	public function setDao($tab="",$cam=array(), $identificador="id", $filtro="")
	{
		// configurando a tabela
		$this->dao["tabela"]  = $tab;
		
		// iniciando matriz campos do dao
		$this->dao["campos"] = array();
		
		// definindo o campo identificador
		if (is_array($identificador))
		{
			$this->dao["identificador"] = implode(",",$identificador);
		}
		else
		{
			$this->dao["identificador"] = $identificador;
		}
		if (!$this->dao["identificador"]) exit("O campo identificador é obrigatório !!!");
		
		// definindo os campos que serão configurados, todos ou somente os que foram passados via parâmetro 
		$campos = "*";
		if (is_array($cam) && count($cam))
		{
			$campos = implode(",",$cam);
		}

		// montando a sql
		$sql = "select $campos from $tab";
		if ($filtro)
		{
			$sql .= " where ".$filtro;
		}
		
		// descobrindo as propriedades de cada campo
		$res = $this->Execute($sql,array(1,0));
		if ($this->db->ErrorMsg()) exit("erro ao executar: ".$this->chave." - ".$this->db->ErrorMsg());
		for ($i = 0; $i < $res->FieldCount(); $i++ )
		{
			$campo = $res->FetchField($i);
			$this->dao["campos"][$campo->name]["titulo"] = $campo->name;
			$this->dao["campos"][$campo->name]["tipo"] 	= $this->getTipo($res->MetaType($campo->type, $campo->max_length));
			if ($campo->max_length) $this->dao["campos"][$campo->name]["tamanhomaximo"] = $campo->max_length;
			if ($filtro)
			{
				$this->dao["campos"][$campo->name]["valor"]	= $res->Fields($campo->name);
			}
			unset($campo);
		}
	}
	
	/**
	 * Executa a atualização DAO
	 * @return boolean
	 */
	public function getAtualiza($sql)
	{
		// executando a atualização
		$res = $this->Execute($sql);
		if ($this->db->ErrorMsg())
		{
			array_push($this->erros,"erro ao executar: ".$this->chave." - ".$this->db->ErrorMsg().$sql);
			return false;
		}
		return true;
	}

}
